package com.bes.bessdk.service;

import static com.bes.bessdk.service.BesOTAConstants.CONFIRM_BYTE_LOW_BATTERY;
import static com.bes.bessdk.service.BesOTAConstants.CONFIRM_BYTE_PASS;
import static com.bes.bessdk.service.BesOTAConstants.OTA_CMD_BREAKPOINT_CHECK_80_NO_CHANGE;
import static com.bes.bessdk.service.BesOTAConstants.USER_MULTIPLE;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import com.bes.bessdk.BesSdkConstants;
import com.bes.bessdk.utils.ArrayUtil;
import com.bes.bessdk.utils.LogUtils;
import com.bes.bessdk.utils.ProfileUtils;
import com.bes.bessdk.utils.SPHelper;
import com.bes.sdk.core.OtaLog;

import android.content.Context;
import android.util.Log;

public class BesOtaCMD {
    private static String TAG = "BesOtaCMD";
    private static byte B_8C = (byte) 0x8C;
    private static byte B_8D = (byte) 0x8D;
    private static byte B_80 = (byte) 0x80;
    private static byte B_81 = (byte) 0x81;
    private static byte B_85 = (byte) 0x85;
    private static byte B_86 = (byte) 0x86;
    private static byte B_87 = (byte) 0x87;
    private static byte B_82 = (byte) 0x82;
    private static byte B_83 = (byte) 0x83;
    private static byte B_88 = (byte) 0x88;
    private static byte B_84 = (byte) 0x84;
    private static byte B_8B = (byte) 0x8B;
    private static byte B_8E = (byte) 0x8E;
    private static byte B_8F = (byte) 0x8F;
    private static byte B_90 = (byte) 0x90;
    private static byte B_91 = (byte) 0x91;
    private static byte B_92 = (byte) 0x92;
    private static byte B_93 = (byte) 0x93;
    private static byte B_94 = (byte) 0x94;
    private static byte B_95 = (byte) 0x95;
    private static byte B_96 = (byte) 0x96;
    private static byte B_99 = (byte) 0x99;
    private static byte B_9A = (byte) 0x9A;
    private static byte B_97 = (byte) 0x97;
    private static byte B_98 = (byte) 0x98;
    private static byte B_9B = (byte) 0x9B;
    private static byte B_9C = (byte) 0x9C;
    private static byte B_9D = (byte) 0x9D;
    private static byte B_9E = (byte) 0x9E;
    private static byte B_7F = (byte) 0x7F;
    private static byte B_7D = (byte) 0x7D;
    private static byte B_7E = (byte) 0x7E;

    private boolean isWithoutResponse = false;
    private boolean isTotaConnect = false;
    private boolean useTotaV2 = false;
    private boolean openCrcConfirm = false;
    private boolean crcConfirm = false;
    private boolean isSppConnect = false;
    private boolean isMultipleBin = false;
    private byte binIdentifier = 0x00;
    private byte[] curConfirmCrc = new byte[4];
    private byte[] magicCode = new byte[] { 0x42, 0x45, 0x53, 0x54 };
    private byte[] emptyByte = new byte[] {};
    private byte[] deviceTypeBytes = new byte[1];
    private byte[] imageSideSelection = new byte[1];
    private byte[] beforeRandomCode;
    private byte[] totaOP = new byte[] { (byte) 0x00, (byte) 0x90 };
    private byte[] mOtaImageData;
    private byte[][][] mDataArr;
    private int deviceType = 0;
    private int USER_FLAG = 0;
    private int curBinCheckLength = 0;
    private int curBinLength = 0;
    private int curAdjustInterval = 0;
    private int curBinCount = 0;
    private int mMtu = BesSdkConstants.DEFAULT_MTU;
    private int pl = 1; // packetType length
    private int ll = 0; // USER length bytes' length: USER_FLAG == 0 ? 0 : 4
    private int checkCount = 0;
    private int packetPayload = 0;
    private int checkBytesLength = 16 * 1024;
    private int totalPacketCount = 0;
    private int onePercentBytes = 0;
    private int curSendLength = 0;
    private int curConfirmLength = 0;
    private int beforeSendLength = 0;
    private int curSendPacketLength = 0;
    private int crcConfirmTimes = 0;
    private String mSwVersion = "";
    private String mHwVersion = "";
    private String deviceId;
    private String curVersionLeft = "";
    private String curVersionRight = "";
    private String versionMsg = "";
    private String roleSwitchRandomID = "";
    private Context mContext;

    public void destoryVariable() {
        mOtaImageData = null;
        packetPayload = 0;
        totalPacketCount = 0;
        onePercentBytes = 0;
        curSendLength = 0;
        beforeSendLength = 0;
        curSendPacketLength = 0;
        crcConfirmTimes = 0;
        crcConfirm = false;
        roleSwitchRandomID = "";
        curConfirmLength = 0;
    }

    public void setOtaUser(int user, boolean isSpp, boolean withoutResponse, boolean isTota, boolean totaV2,
            String identifier) {
        Log.i(TAG, "setOtaUser --------");
        USER_FLAG = user;
        isSppConnect = isSpp;
        isWithoutResponse = withoutResponse;
        isTotaConnect = isTota;
        useTotaV2 = totaV2;
        deviceId = identifier;
        curConfirmLength = 0;
        if (isSppConnect) {
            checkBytesLength = 32 * 1024;
        }
        if (USER_FLAG == 1) {
            ll = 4;
        } else {
            ll = 0;
        }
    }

    // 0：stereo 1：left 2:right 3:both 4:both diff
    public void setImageSideSelection(int type) {
        Log.i(TAG, "setImageSideSelection type--------" + type);
        if (type == 0) {
            imageSideSelection[0] = (byte) 0x00;
        } else if (type == 1) {
            imageSideSelection[0] = (byte) 0x01;
        } else if (type == 2) {
            imageSideSelection[0] = (byte) 0x10;
        } else if (type == 3) {
            imageSideSelection[0] = (byte) 0x11;
        }
    }

    public byte[] getCurCheckSegmentLengthCMD() {
        Log.i(TAG, "getCurCheckSegmentLengthCMD --------");
        byte[] pt = new byte[] { (byte) B_7D };
        byte[] lBytes = emptyByte;
        if (USER_FLAG == 1) {
            lBytes = ArrayUtil.intToBytesLittle(magicCode.length);
        }
        byte[] bytes = ArrayUtil.bytesSplic(pt, lBytes, magicCode, emptyByte);

        return bytes;
    }

    public byte[] getCurrentVersionCMD() {
        Log.i(TAG, "getCurrentVersionCMD --------");
        byte[] pt = new byte[] { (byte) B_8E };
        byte[] lBytes = emptyByte;
        if (USER_FLAG == 1) {
            lBytes = ArrayUtil.intToBytesLittle(magicCode.length);
        }
        byte[] bytes = ArrayUtil.bytesSplic(pt, lBytes, magicCode, emptyByte);

        if (isTotaConnect) {
            return convertToTotaCMD(bytes);
        }
        return bytes;
    }

    public int getCurrentDeviceType() {
        Log.i(TAG, "getCurrentDeviceType --------");
        return deviceType;
    }

    public String getCurrentVersion() {
        String v = "";
        if (deviceType == BesOTAConstants.DEVICE_TYPE_STEREO) {
            Log.i(TAG, "getCurrentVersion: -----" + curVersionLeft);
            // v = "stereo:" + curVersionLeft + "\n" + versionMsg;
            v = curVersionLeft;
            versionMsg = "";
        } else if (deviceType == BesOTAConstants.DEVICE_TYPE_TWS_CONNECT_LEFT) {
            v = "TWS left:" + curVersionLeft;
        } else if (deviceType == BesOTAConstants.DEVICE_TYPE_TWS_CONNECT_RIGHT) {
            v = "TWS right:" + curVersionRight;
        }
        return v;
    }

    public String getRoleSwitchRandomID() {
        return roleSwitchRandomID;
    }

    public byte[] getOtaProtocolVersionCMD(boolean currentOrLegacy) {
        Log.i(TAG, "getOtaProtocolVersionCMD --------");
        byte[] pt = new byte[] { (byte) B_99 };
        byte[] lBytes = emptyByte;
        byte[] vBytes = new byte[4];
        if (USER_FLAG == 1) {
            lBytes = ArrayUtil.intToBytesLittle(vBytes.length);
        }
        vBytes[3] = currentOrLegacy ? (byte) 0x01 : (byte) 0x00;
        byte[] bytes = ArrayUtil.bytesSplic(pt, lBytes, emptyByte, vBytes);
        if (isTotaConnect) {
            return convertToTotaCMD(bytes);
        }
        return bytes;
    }

    public byte[] getOtaExitCMD() {
        Log.i(TAG, "getOtaExitCMD --------");
        byte[] pt = new byte[] { (byte) B_94 };
        byte[] lBytes = emptyByte;
        byte[] vBytes = new byte[1];
        if (USER_FLAG == 1) {
            lBytes = ArrayUtil.intToBytesLittle(0);
        }
        vBytes[0] = 0x01;
        byte[] bytes = ArrayUtil.bytesSplic(pt, lBytes, emptyByte, vBytes);
        if (isTotaConnect) {
            return convertToTotaCMD(bytes);
        }
        return bytes;
    }

    public byte[] getSetOtaUserCMD(int user) {
        Log.i(TAG, "getSetOtaUserCMD --------");
        byte[] pt = new byte[] { (byte) B_97 };
        byte[] lBytes = emptyByte;
        byte[] vBytes = new byte[1];
        if (USER_FLAG == 1) {
            lBytes = ArrayUtil.intToBytesLittle(vBytes.length);
        }
        byte userByte = (byte) user;
        if (user == USER_MULTIPLE) {
            isMultipleBin = true;
        }
        vBytes[0] = userByte;
        byte[] bytes = ArrayUtil.bytesSplic(pt, lBytes, emptyByte, vBytes);

        if (isTotaConnect) {
            return convertToTotaCMD(bytes);
        }
        return bytes;
    }

    // 0x01: apply NORMAL MODE
    // 0x02: apply FAST MODE
    public byte[] getSetUpgrateTypeCMD(int type) {
        Log.i(TAG, "getSetUpgrateTypeCMD --------");
        byte[] pt = new byte[] { (byte) B_9D };
        byte[] lBytes = emptyByte;
        byte[] tBytes = new byte[1];
        if (USER_FLAG == 1) {
            lBytes = ArrayUtil.intToBytesLittle(tBytes.length);
        }
        byte tByte = 0x00;
        if (type == 1) {
            tByte = 0x01;
        } else if (type == 2) {
            tByte = 0x02;
        }
        tBytes[0] = tByte;
        byte[] bytes = ArrayUtil.bytesSplic(pt, lBytes, emptyByte, tBytes);
        if (isTotaConnect) {
            return convertToTotaCMD(bytes);
        }
        return bytes;
    }

    public byte[] getROLESwitchRandomIDCMD() {
        Log.i(TAG, "getROLESwitchRandomIDCMD --------");
        byte[] pt = new byte[] { (byte) B_9B };
        byte[] lBytes = emptyByte;
        if (USER_FLAG == 1) {
            lBytes = ArrayUtil.intToBytesLittle(0);
        }
        byte[] bytes = ArrayUtil.bytesSplic(pt, lBytes, emptyByte, emptyByte);
        if (isTotaConnect) {
            return convertToTotaCMD(bytes);
        }
        return bytes;
    }

    public byte[] getSelectSideCMD() {
        Log.i(TAG, "getSelectSideCMD --------");
        byte[] pt = new byte[] { (byte) B_90 };
        byte[] lBytes = emptyByte;
        if (USER_FLAG == 1) {
            lBytes = ArrayUtil.intToBytesLittle(1);
        }
        byte[] bytes = ArrayUtil.bytesSplic(pt, lBytes, emptyByte, imageSideSelection);
        if (isTotaConnect) {
            return convertToTotaCMD(bytes);
        }
        return bytes;
    }

    public byte[] getCheckBreakPointCMD(Context context) {
        Log.i(TAG, "getCheckBreakPointCMD --------");
        mContext = context;
        byte[] pt = new byte[] { (byte) B_8C };
        byte[] lBytes = emptyByte;
        byte[] randomCode = new byte[32];
        byte[] segmentBytes = new byte[] { 0x01, 0x02, 0x03, 0x04 };
        byte[] crc32Bytes = new byte[4];
        int dataL = randomCode.length + segmentBytes.length + crc32Bytes.length;
        if (USER_FLAG == 1) {
            lBytes = ArrayUtil.intToBytesLittle(magicCode.length + dataL);
        }
        byte[] data = new byte[dataL];

        String randomCodestr = null;
        randomCodestr =
                (String) SPHelper.getPreference(mContext, BesOTAConstants.BES_OTA_RANDOM_CODE_LEFT + deviceId, "");
        if (randomCodestr != null && randomCodestr != "") {
            randomCode = ArrayUtil.toBytes(randomCodestr);
        }
        beforeRandomCode = randomCode;

        byte[] crc32_data = new byte[36];
        System.arraycopy(randomCode, 0, crc32_data, 0, randomCode.length);
        System.arraycopy(segmentBytes, 0, crc32_data, randomCode.length, segmentBytes.length);

        long crc32 = ArrayUtil.crc32(crc32_data, 0, 36);
        crc32Bytes[0] = (byte) crc32;
        crc32Bytes[1] = (byte) (crc32 >> 8);
        crc32Bytes[2] = (byte) (crc32 >> 16);
        crc32Bytes[3] = (byte) (crc32 >> 24);

        System.arraycopy(randomCode, 0, data, 0, randomCode.length);
        System.arraycopy(segmentBytes, 0, data, randomCode.length, segmentBytes.length);
        System.arraycopy(crc32Bytes, 0, data, randomCode.length + segmentBytes.length, crc32Bytes.length);

        byte[] bytes = ArrayUtil.bytesSplic(pt, lBytes, magicCode, data);

        if (isTotaConnect) {
            return convertToTotaCMD(bytes);
        }
        return bytes;
    }

    public byte[] getStartOTAPacketCMD(byte[] fileBytes) {
        Log.i(TAG, "getStartOTAPacketCMD --------");
        byte[] pt = new byte[] { (byte) B_80 };
        byte[] imageSize = new byte[4];
        byte[] crc32OfImage = new byte[4];
        byte[] lBytes = emptyByte;
        int dataL = imageSize.length + crc32OfImage.length;
        if (USER_FLAG == 1) {
            lBytes = ArrayUtil.intToBytesLittle(magicCode.length + dataL);
        }
        byte[] data = new byte[dataL];
        Log.i(TAG, "getStartOTAPacketCMD totalSize: --------" + fileBytes.length);
        // d4b71a00
        // int m = 0;
        // if((dataSize % 256) > 0) {
        // m = dataSize / 256;
        // dataSize = (m + 1) * 256;
        // }
        int dataSize = fileBytes.length;

        byte[] iamgeBytes = fileBytes;
        if (isMultipleBin) {
            crcConfirmTimes = 0;
            curSendPacketLength = packetPayload;
            byte[] binCountByte = new byte[4];
            System.arraycopy(iamgeBytes, 0, binCountByte, 0, binCountByte.length);
            int binCount = ArrayUtil.bytesToIntLittle(binCountByte);
            curBinCount = binCount;
            Log.i(TAG, "getStartOTAPacketCMD binCount: ---------" + binCount);
            int matchBinLength = 0;
            for (int i = 0; i < binCount; i++) {
                byte[] binLengthByte = new byte[4];
                System.arraycopy(iamgeBytes, 4 + i * 8 + 4, binLengthByte, 0, binLengthByte.length);
                int binLength = ArrayUtil.bytesToIntLittle(binLengthByte);
                Log.i(TAG, "getStartOTAPacketCMD binLength: ---------" + binLength);
                matchBinLength = matchBinLength + binLength;
                Log.i(TAG, "getStartOTAPacketCMD matchBinLength: ------" + matchBinLength);
                Log.i(TAG, "getStartOTAPacketCMD curSendLength: ------" + curSendLength);
                Log.i(TAG, "getStartOTAPacketCMD (i == (binCount - 1)): --------" + (i == (binCount - 1)));
                if (matchBinLength > curSendLength || (i == (binCount - 1))) {
                    curBinLength = binLength;
                    beforeSendLength = curSendLength - (matchBinLength - binLength);
                    binIdentifier = iamgeBytes[4 + i * 8];
                    Log.i(TAG, "getStartOTAPacketCMD binIdentifier: ---------"
                            + ArrayUtil.toHex(new byte[] { binIdentifier }));
                    curBinCheckLength = matchBinLength;
                    byte[] curBinData = new byte[binLength];
                    System.arraycopy(iamgeBytes, 4 + binCount * 8 + matchBinLength - binLength, curBinData, 0,
                            binLength);
                    iamgeBytes = curBinData;
                    dataSize = binLength;
                    break;
                }
            }
        }
        long crc32 = ArrayUtil.crc32(iamgeBytes, 0, dataSize);
        imageSize = ArrayUtil.intToBytesLittle(dataSize);

        crc32OfImage[0] = (byte) crc32;
        crc32OfImage[1] = (byte) (crc32 >> 8);
        crc32OfImage[2] = (byte) (crc32 >> 16);
        crc32OfImage[3] = (byte) (crc32 >> 24);
        System.arraycopy(imageSize, 0, data, 0, imageSize.length);
        System.arraycopy(crc32OfImage, 0, data, imageSize.length, crc32OfImage.length);
        byte[] bytes = ArrayUtil.bytesSplic(pt, lBytes, magicCode, data);
        if (isMultipleBin) {
            bytes = ArrayUtil.byteMerger(new byte[] { binIdentifier }, bytes);
        }
        if (isTotaConnect) {
            return convertToTotaCMD(bytes);
        }
        return bytes;

    }

    public byte[] getStartOTAPacketCMD(String path) {
        Log.i(TAG, "getStartOTAPacketCMD path--------" + path);
        byte[] pt = new byte[] { (byte) B_80 };
        byte[] imageSize = new byte[4];
        byte[] crc32OfImage = new byte[4];
        byte[] lBytes = emptyByte;
        int dataL = imageSize.length + crc32OfImage.length;
        if (USER_FLAG == 1) {
            lBytes = ArrayUtil.intToBytesLittle(magicCode.length + dataL);
        }
        byte[] data = new byte[dataL];
        FileInputStream inputStream = null;
        try {
            inputStream = new FileInputStream(path);
            int totalSize = inputStream.available();
            Log.i(TAG, "getStartOTAPacketCMD totalSize: --------" + totalSize);
            int dataSize = totalSize;
            // d4b71a00
            // int m = 0;
            // if((dataSize % 256) > 0) {
            // m = dataSize / 256;
            // dataSize = (m + 1) * 256;
            // }
            byte[] iamgeBytes = new byte[dataSize];
            inputStream.read(iamgeBytes, 0, dataSize);
            inputStream.close();
            if (isMultipleBin) {
                crcConfirmTimes = 0;
                curSendPacketLength = packetPayload;
                byte[] binCountByte = new byte[4];
                System.arraycopy(iamgeBytes, 0, binCountByte, 0, binCountByte.length);
                int binCount = ArrayUtil.bytesToIntLittle(binCountByte);
                curBinCount = binCount;
                Log.i(TAG, "getStartOTAPacketCMD binCount: ---------" + binCount);
                int matchBinLength = 0;
                for (int i = 0; i < binCount; i++) {
                    byte[] binLengthByte = new byte[4];
                    System.arraycopy(iamgeBytes, 4 + i * 8 + 4, binLengthByte, 0, binLengthByte.length);
                    int binLength = ArrayUtil.bytesToIntLittle(binLengthByte);
                    Log.i(TAG, "getStartOTAPacketCMD binLength: ---------" + binLength);
                    matchBinLength = matchBinLength + binLength;
                    Log.i(TAG, "getStartOTAPacketCMD matchBinLength: ------" + matchBinLength);
                    Log.i(TAG, "getStartOTAPacketCMD curSendLength: ------" + curSendLength);
                    Log.i(TAG, "getStartOTAPacketCMD (i == (binCount - 1)): --------" + (i == (binCount - 1)));
                    if (matchBinLength > curSendLength || (i == (binCount - 1))) {
                        curBinLength = binLength;
                        beforeSendLength = curSendLength - (matchBinLength - binLength);
                        binIdentifier = iamgeBytes[4 + i * 8];
                        Log.i(TAG, "getStartOTAPacketCMD binIdentifier: ---------"
                                + ArrayUtil.toHex(new byte[] { binIdentifier }));
                        curBinCheckLength = matchBinLength;
                        byte[] curBinData = new byte[binLength];
                        System.arraycopy(iamgeBytes, 4 + binCount * 8 + matchBinLength - binLength, curBinData, 0,
                                binLength);
                        iamgeBytes = curBinData;
                        dataSize = binLength;
                        break;
                    }
                }
            }
            long crc32 = ArrayUtil.crc32(iamgeBytes, 0, dataSize);
            imageSize = ArrayUtil.intToBytesLittle(dataSize);

            crc32OfImage[0] = (byte) crc32;
            crc32OfImage[1] = (byte) (crc32 >> 8);
            crc32OfImage[2] = (byte) (crc32 >> 16);
            crc32OfImage[3] = (byte) (crc32 >> 24);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.arraycopy(imageSize, 0, data, 0, imageSize.length);
        System.arraycopy(crc32OfImage, 0, data, imageSize.length, crc32OfImage.length);
        byte[] bytes = ArrayUtil.bytesSplic(pt, lBytes, magicCode, data);
        if (isMultipleBin) {
            bytes = ArrayUtil.byteMerger(new byte[] { binIdentifier }, bytes);
        }
        if (isTotaConnect) {
            return convertToTotaCMD(bytes);
        }
        return bytes;
    }
    /*
     * public byte[] getOTAConfigureCMD(byte[] path, Context context) { Log.i(TAG, "getOTAConfigureCMD --------"); //fix
     * :role switch state crcConfirm = false; mContext = context; byte[] pt = new byte[]{(byte) B_86}; byte[]
     * followingDataLBytes = new byte[4]; byte[] startLocationToWriteImageBytes = new byte[4]; byte[] configBytes = new
     * byte[4]; byte[] newBTName = new byte[32]; byte[] newBLEName = new byte[32]; byte[] newBTAddr = new byte[6];
     * byte[] newBLEAddr = new byte[6]; byte[] crcOfConfiguration = new byte[4];
     * 
     * byte[] lBytes = emptyByte; int dataL = followingDataLBytes.length + startLocationToWriteImageBytes.length +
     * configBytes.length + newBTName.length + newBLEName.length + newBTAddr.length + newBLEAddr.length +
     * crcOfConfiguration.length; if (USER_FLAG == 1) { lBytes = ArrayUtil.intToBytesLittle(dataL); } byte[] data = new
     * byte[dataL]; followingDataLBytes = ArrayUtil.intToBytesLittle(dataL - followingDataLBytes.length); int totalSize
     * =path.length; int dataSize = totalSize; byte[] iamgeBytes =path; startLocationToWriteImageBytes[0] =
     * iamgeBytes[dataSize - 4]; startLocationToWriteImageBytes[1] = iamgeBytes[dataSize - 3];
     * startLocationToWriteImageBytes[2] = iamgeBytes[dataSize - 2];
     * 
     * boolean clearUserData = (boolean) SPHelper.getPreference(mContext,
     * BesOTAConstants.KEY_OTA_CONFIG_CLEAR_USER_DATA, BesOTAConstants.DEFAULT_CLEAR_USER_DATA); boolean updateBtAddress
     * = (boolean) SPHelper.getPreference(mContext, BesOTAConstants.KEY_OTA_CONFIG_UPDATE_BT_ADDRESS,
     * BesOTAConstants.DEFAULT_UPDATE_BT_ADDRESS); boolean updateBtName = (boolean) SPHelper.getPreference(mContext,
     * BesOTAConstants.KEY_OTA_CONFIG_UPDATE_BT_NAME, BesOTAConstants.DEFAULT_UPDATE_BT_NAME); boolean updateBleAddress
     * = (boolean) SPHelper.getPreference(mContext, BesOTAConstants.KEY_OTA_CONFIG_UPDATE_BLE_ADDRESS,
     * BesOTAConstants.DEFAULT_UPDATE_BLE_ADDRESS); boolean updateBleName = (boolean) SPHelper.getPreference(mContext,
     * BesOTAConstants.KEY_OTA_CONFIG_UPDATE_BLE_NAME, BesOTAConstants.DEFAULT_UPDATE_BLE_NAME);
     * 
     * byte enable = 0x00; enable |= (clearUserData ? 0x01 : 0x00); enable |= (updateBtName ? (0x01 << 1) : 0x00);
     * enable |= (updateBleName ? (0x01 << 2) : 0x00); enable |= (updateBtAddress ? (0x01 << 3) : 0x00); enable |=
     * (updateBleAddress ? (0x01 << 4) : 0x00); configBytes[0] = enable;
     * 
     * updateBtName = true; if (updateBtName) { String btName = (String) SPHelper.getPreference(mContext,
     * BesOTAConstants.KEY_OTA_CONFIG_UPDATE_BT_NAME_VALUE, ""); // String name16 = ArrayUtil.str2HexStr(btName); byte[]
     * namebytes = btName.getBytes(); int btNameLength = namebytes.length; if (btNameLength > 32) { btNameLength = 32; }
     * for (int i = 0; i < namebytes.length; i++) { newBTName[i] = namebytes[i]; } } if (updateBleName) { String bleName
     * = (String) SPHelper.getPreference(mContext, BesOTAConstants.KEY_OTA_CONFIG_UPDATE_BLE_NAME_VALUE, ""); // String
     * name16 = ArrayUtil.str2HexStr(bleName); byte[] namebytes = bleName.getBytes(); int bleNameLength =
     * namebytes.length; if (bleNameLength > 32) { bleNameLength = 32; } for (int i = 0; i < namebytes.length; i++) {
     * newBLEName[i] = namebytes[i]; } } if (updateBtAddress) { String btAdress = (String)
     * SPHelper.getPreference(mContext, BesOTAConstants.KEY_OTA_CONFIG_UPDATE_BT_ADDRESS_VALUE, ""); // String name16 =
     * ArrayUtil.str2HexStr(btAdress); // byte[] namebytes = ArrayUtil.to2Bytes(name16); Log.i("TAG",
     * "getOTAConfigureCMD: " + btAdress +"  "+btAdress.length()); // Log.i("TAG", "getOTAConfigureCMD: " + name16); //
     * Log.i("TAG", "getOTAConfigureCMD: " + namebytes.length + "byte" + ArrayUtil.toHex(namebytes)); for (int i = 0; i
     * < 6; i++) { newBTAddr[5 - i] = Integer.valueOf(btAdress.substring(i, i * 2 + 2), 16).byteValue(); Log.i("TAG",
     * "getOTAConfigureCMD: " + ArrayUtil.toHex(newBTAddr)); } } if (updateBleAddress) { String bleAdress = (String)
     * SPHelper.getPreference(mContext, BesOTAConstants.KEY_OTA_CONFIG_UPDATE_BLE_ADDRESS_VALUE, ""); // String name16 =
     * ArrayUtil.str2HexStr(bleAdress); // byte[] namebytes = ArrayUtil.toBytes(name16); for (int i = 0; i < 6; i++) {
     * newBLEAddr[5 - i] = Integer.valueOf(bleAdress.substring(i, i * 2 + 2), 16).byteValue(); } }
     * 
     * byte[] half0 = ArrayUtil.bytesSplic(followingDataLBytes, startLocationToWriteImageBytes, configBytes, newBTName);
     * byte[] half1 = ArrayUtil.bytesSplic(newBLEName, newBTAddr, newBLEAddr, crcOfConfiguration);
     * 
     * System.arraycopy(half0, 0, data, 0, half0.length); System.arraycopy(half1, 0, data, half0.length, half1.length);
     * 
     * long crc32 = ArrayUtil.crc32(data, 0, dataL - 4); crcOfConfiguration[0] = (byte) crc32; crcOfConfiguration[1] =
     * (byte) (crc32 >> 8); crcOfConfiguration[2] = (byte) (crc32 >> 16); crcOfConfiguration[3] = (byte) (crc32 >> 24);
     * System.arraycopy(crcOfConfiguration, 0, data, dataL - crcOfConfiguration.length, crcOfConfiguration.length);
     * 
     * 
     * byte[] bytes = ArrayUtil.bytesSplic(pt, lBytes, emptyByte, data);
     * 
     * if (isMultipleBin) { bytes = ArrayUtil.byteMerger(new byte[]{binIdentifier}, bytes); } if (isTotaConnect) {
     * return convertToTotaCMD(bytes); } return bytes; }
     */

    public byte[] getOTAConfigureCMD(String path, Context context) {
        Log.i(TAG, "getOTAConfigureCMD path--------" + path);
        // fix :role switch state
        crcConfirm = false;
        mContext = context;
        byte[] pt = new byte[] { (byte) B_86 };
        byte[] followingDataLBytes = new byte[4];
        byte[] startLocationToWriteImageBytes = new byte[4];
        byte[] configBytes = new byte[4];
        byte[] newBTName = new byte[isMultipleBin ? 16 : 32];
        byte[] newBLEName = new byte[isMultipleBin ? 16 : 32];
        byte[] newBTAddr = new byte[6];
        byte[] newBLEAddr = new byte[6];
        byte[] crcOfConfiguration = new byte[4];

        byte[] lBytes = emptyByte;
        int dataL = followingDataLBytes.length + startLocationToWriteImageBytes.length + configBytes.length
                + newBTName.length + newBLEName.length + newBTAddr.length + newBLEAddr.length
                + crcOfConfiguration.length;
        if (USER_FLAG == 1) {
            lBytes = ArrayUtil.intToBytesLittle(dataL);
        }
        byte[] data = new byte[dataL];
        followingDataLBytes = ArrayUtil.intToBytesLittle(dataL - followingDataLBytes.length);
        FileInputStream inputStream = null;
        try {
            inputStream = new FileInputStream(path);
            int totalSize = inputStream.available();
            int dataSize = totalSize;
            byte[] iamgeBytes = new byte[dataSize];
            inputStream.read(iamgeBytes, 0, dataSize);
            inputStream.close();

            startLocationToWriteImageBytes[0] = iamgeBytes[dataSize - 4];
            startLocationToWriteImageBytes[1] = iamgeBytes[dataSize - 3];
            startLocationToWriteImageBytes[2] = iamgeBytes[dataSize - 2];

            boolean clearUserData = (boolean) SPHelper.getPreference(mContext,
                    BesOTAConstants.KEY_OTA_CONFIG_CLEAR_USER_DATA, BesOTAConstants.DEFAULT_CLEAR_USER_DATA);
            boolean updateBtAddress = (boolean) SPHelper.getPreference(mContext,
                    BesOTAConstants.KEY_OTA_CONFIG_UPDATE_BT_ADDRESS, BesOTAConstants.DEFAULT_UPDATE_BT_ADDRESS);
            boolean updateBtName = (boolean) SPHelper.getPreference(mContext,
                    BesOTAConstants.KEY_OTA_CONFIG_UPDATE_BT_NAME, BesOTAConstants.DEFAULT_UPDATE_BT_NAME);
            boolean updateBleAddress = (boolean) SPHelper.getPreference(mContext,
                    BesOTAConstants.KEY_OTA_CONFIG_UPDATE_BLE_ADDRESS, BesOTAConstants.DEFAULT_UPDATE_BLE_ADDRESS);
            boolean updateBleName = (boolean) SPHelper.getPreference(mContext,
                    BesOTAConstants.KEY_OTA_CONFIG_UPDATE_BLE_NAME, BesOTAConstants.DEFAULT_UPDATE_BLE_NAME);

            byte enable = 0x00;
            enable |= (clearUserData ? 0x01 : 0x00);
            enable |= (updateBtName ? (0x01 << 1) : 0x00);
            enable |= (updateBleName ? (0x01 << 2) : 0x00);
            enable |= (updateBtAddress ? (0x01 << 3) : 0x00);
            enable |= (updateBleAddress ? (0x01 << 4) : 0x00);
            configBytes[0] = enable;

            updateBtName = true;
            if (updateBtName) {
                String btName = (String) SPHelper.getPreference(mContext,
                        BesOTAConstants.KEY_OTA_CONFIG_UPDATE_BT_NAME_VALUE, "");
                // String name16 = ArrayUtil.str2HexStr(btName);
                byte[] namebytes = btName.getBytes();
                int btNameLength = namebytes.length;
                if (btNameLength > (isMultipleBin ? 16 : 32)) {
                    btNameLength = (isMultipleBin ? 16 : 32);
                }
                for (int i = 0; i < namebytes.length; i++) {
                    newBTName[i] = namebytes[i];
                }
            }
            if (updateBleName) {
                String bleName = (String) SPHelper.getPreference(mContext,
                        BesOTAConstants.KEY_OTA_CONFIG_UPDATE_BLE_NAME_VALUE, "");
                // String name16 = ArrayUtil.str2HexStr(bleName);
                byte[] namebytes = bleName.getBytes();
                int bleNameLength = namebytes.length;
                if (bleNameLength > (isMultipleBin ? 16 : 32)) {
                    bleNameLength = (isMultipleBin ? 16 : 32);
                }
                for (int i = 0; i < namebytes.length; i++) {
                    newBLEName[i] = namebytes[i];
                }
            }
            if (updateBtAddress) {
                String btAdress = (String) SPHelper.getPreference(mContext,
                        BesOTAConstants.KEY_OTA_CONFIG_UPDATE_BT_ADDRESS_VALUE, "");
                // String name16 = ArrayUtil.str2HexStr(btAdress);
                // byte[] namebytes = ArrayUtil.to2Bytes(name16);
                // Log.i("TAG", "getOTAConfigureCMD: " + name16);
                // Log.i("TAG", "getOTAConfigureCMD: " + namebytes.length + "byte" + ArrayUtil.toHex(namebytes));
                for (int i = 0; i < 6; i++) {
                    newBTAddr[5 - i] = Integer.valueOf(btAdress.substring(i, i * 2 + 2), 16).byteValue();
                }
            }
            if (updateBleAddress) {
                String bleAdress = (String) SPHelper.getPreference(mContext,
                        BesOTAConstants.KEY_OTA_CONFIG_UPDATE_BLE_ADDRESS_VALUE, "");
                // String name16 = ArrayUtil.str2HexStr(bleAdress);
                // byte[] namebytes = ArrayUtil.toBytes(name16);
                for (int i = 0; i < 6; i++) {
                    newBLEAddr[5 - i] = Integer.valueOf(bleAdress.substring(i, i * 2 + 2), 16).byteValue();
                }
            }

            byte[] half0 =
                    ArrayUtil.bytesSplic(followingDataLBytes, startLocationToWriteImageBytes, configBytes, newBTName);
            byte[] half1 = ArrayUtil.bytesSplic(newBLEName, newBTAddr, newBLEAddr, crcOfConfiguration);

            System.arraycopy(half0, 0, data, 0, half0.length);
            System.arraycopy(half1, 0, data, half0.length, half1.length);

            long crc32 = ArrayUtil.crc32(data, 0, dataL - 4);
            crcOfConfiguration[0] = (byte) crc32;
            crcOfConfiguration[1] = (byte) (crc32 >> 8);
            crcOfConfiguration[2] = (byte) (crc32 >> 16);
            crcOfConfiguration[3] = (byte) (crc32 >> 24);
            System.arraycopy(crcOfConfiguration, 0, data, dataL - crcOfConfiguration.length, crcOfConfiguration.length);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        byte[] bytes = ArrayUtil.bytesSplic(pt, lBytes, emptyByte, data);
        if (isMultipleBin) {
            bytes = ArrayUtil.byteMerger(new byte[] { binIdentifier }, bytes);
        }
        if (isTotaConnect) {
            return convertToTotaCMD(bytes);
        }
        return bytes;
    }

    public byte[][] getPacketData(String path, boolean isBle) {
        Log.i(TAG, "getPacketData --------");
        if (mOtaImageData == null) {
            readlocalImageData(path, isBle);
        }
        if (crcConfirmTimes == mDataArr.length) {
            return null;
        }
        byte[][] packData = mDataArr[crcConfirmTimes];
        byte[][] lastData = new byte[packData.length][];
        for (int i = 0; i < packData.length; i++) {
            if (i == (packData.length - 1)) {
                lastData[i] = packData[i];
            } else {
                byte[] lBytes = emptyByte;
                byte[] pt = new byte[] { (byte) B_85 };
                byte[] packetData = packData[i];
                int dataL = packetData.length;
                if (USER_FLAG == 1) {
                    lBytes = ArrayUtil.intToBytesLittle(dataL);
                }
                byte[] bytes = ArrayUtil.bytesSplic(pt, lBytes, emptyByte, packetData);
                if (isMultipleBin) {
                    bytes = ArrayUtil.byteMerger(new byte[] { binIdentifier }, bytes);
                }
                if (isTotaConnect) {
                    bytes = convertToTotaCMD(bytes);
                }
                lastData[i] = bytes;
            }
        }
        return lastData;
    }

    public byte[] get82CMD(byte[] data) {
        Log.i(TAG, "get82CMD --------");
        byte[] lBytes = emptyByte;
        byte[] crcPt = new byte[] { (byte) B_82 };
        byte[] crc32OfSegment = getCrc32OfSegment(data);
        int crcDataL = magicCode.length + crc32OfSegment.length;
        if (USER_FLAG == 1) {
            lBytes = ArrayUtil.intToBytesLittle(crcDataL);
        }
        byte[] bytes = ArrayUtil.bytesSplic(crcPt, lBytes, magicCode, crc32OfSegment);
        if (isMultipleBin) {
            bytes = ArrayUtil.byteMerger(new byte[] { binIdentifier }, bytes);
        }
        if (isTotaConnect) {
            return convertToTotaCMD(bytes);
        }
        return bytes;
    }

    public byte[] get88CMD() {
        Log.i(TAG, "get88CMD --------");
        byte[] lBytes = emptyByte;
        byte[] wholeCrcPt = new byte[] { (byte) B_88 };
        if (USER_FLAG == 1) {
            lBytes = ArrayUtil.intToBytesLittle(0);
        }
        byte[] bytes = ArrayUtil.bytesSplic(wholeCrcPt, lBytes, emptyByte, emptyByte);
        if (isMultipleBin) {
            bytes = ArrayUtil.byteMerger(new byte[] { binIdentifier }, bytes);
        }
        if (isTotaConnect) {
            return convertToTotaCMD(bytes);
        }
        return bytes;
    }

    public int getCurSendLength() {
        return crcConfirmTimes * checkBytesLength;
    }

    public byte[] getDataPacketCMD(String path, boolean isBle) {
        Log.i(TAG, "getDataPacketCMD --------");
        if (mOtaImageData == null) {
            readlocalImageData(path, isBle);
        }
        byte[] lBytes = emptyByte;
        if (crcConfirm) {
            crcConfirm = false;
            byte[] crcPt = new byte[] { (byte) B_82 };
            byte[] crc32OfSegment = getCrc32OfSegment();
            int crcDataL = magicCode.length + crc32OfSegment.length;
            if (USER_FLAG == 1) {
                lBytes = ArrayUtil.intToBytesLittle(crcDataL);
            }
            byte[] bytes = ArrayUtil.bytesSplic(crcPt, lBytes, magicCode, crc32OfSegment);
            if (isMultipleBin) {
                bytes = ArrayUtil.byteMerger(new byte[] { binIdentifier }, bytes);
            }
            if (isTotaConnect) {
                return convertToTotaCMD(bytes);
            }
            return bytes;
        }

        int totalBinLength = mOtaImageData.length;
        if (isMultipleBin) {
            totalBinLength = curBinCheckLength;
        }
        if (crcConfirmTimes == mDataArr.length || beforeSendLength == totalBinLength
                || curSendLength == totalBinLength) {
            byte[] wholeCrcPt = new byte[] { (byte) B_88 };
            if (USER_FLAG == 1) {
                lBytes = ArrayUtil.intToBytesLittle(0);
            }
            byte[] bytes = ArrayUtil.bytesSplic(wholeCrcPt, lBytes, emptyByte, emptyByte);

            if (isMultipleBin) {
                bytes = ArrayUtil.byteMerger(new byte[] { binIdentifier }, bytes);
            }

            if (isTotaConnect) {
                return convertToTotaCMD(bytes);
            }
            return bytes;
        }

        byte[] pt = new byte[] { (byte) B_85 };
        byte[] packetData = getDataPacket();
        int dataL = packetData.length;
        if (USER_FLAG == 1) {
            lBytes = ArrayUtil.intToBytesLittle(dataL);
        }
        byte[] bytes = ArrayUtil.bytesSplic(pt, lBytes, emptyByte, packetData);
        if (isMultipleBin) {
            bytes = ArrayUtil.byteMerger(new byte[] { binIdentifier }, bytes);
        }
        if (isTotaConnect) {
            return convertToTotaCMD(bytes);
        }
        return bytes;
    }

    /**
    public byte[] getDataPacketCMD(byte[] path, boolean isBle) {
        Log.i(TAG, "getDataPacketCMD --------");
        if (mOtaImageData == null) {
            readlocalImageData(path, isBle);
        }
        byte[] lBytes = emptyByte;
    
        if (crcConfirm) {
            crcConfirm = false;
            byte[] crcPt = new byte[]{(byte) B_82};
            byte[] crc32OfSegment = getCrc32OfSegment();
            curConfirmCrc = crc32OfSegment;
            int crcDataL = magicCode.length + crc32OfSegment.length;
            if (USER_FLAG == 1) {
                lBytes = ArrayUtil.intToBytesLittle(crcDataL);
            }
    
            byte[] bytes = ArrayUtil.bytesSplic(crcPt, lBytes, magicCode, crc32OfSegment);
    
            if (isMultipleBin) {
                bytes = ArrayUtil.byteMerger(new byte[]{binIdentifier}, bytes);
            }
    
            if (isTotaConnect) {
                return convertToTotaCMD(bytes);
            }
            return bytes;
        }
    
        int totalBinLength = mOtaImageData.length;
        if (isMultipleBin) {
            totalBinLength = curBinCheckLength;
        }
        if (beforeSendLength == totalBinLength || curSendLength == totalBinLength) {
            byte[] wholeCrcPt = new byte[]{(byte) B_88};
            if (USER_FLAG == 1) {
                lBytes = ArrayUtil.intToBytesLittle(0);
            }
            byte[] bytes = ArrayUtil.bytesSplic(wholeCrcPt, lBytes, emptyByte, emptyByte);
    
            if (isMultipleBin) {
                bytes = ArrayUtil.byteMerger(new byte[]{binIdentifier}, bytes);
            }
    
            if (isTotaConnect) {
                return convertToTotaCMD(bytes);
            }
            return bytes;
        }
    
        byte[] pt = new byte[]{(byte) B_85};
        byte[] packetData = getDataPacket();
        int dataL = packetData.length;
        if (USER_FLAG == 1) {
            lBytes = ArrayUtil.intToBytesLittle(dataL);
        }
        byte[] bytes = ArrayUtil.bytesSplic(pt, lBytes, emptyByte, packetData);
        if (isMultipleBin) {
            bytes = ArrayUtil.byteMerger(new byte[]{binIdentifier}, bytes);
        }
        if (isTotaConnect) {
            return convertToTotaCMD(bytes);
        }
        return bytes;
    }**/

    public void readlocalImageData(String path, boolean isBle) {
        Log.i(TAG, "readlocalImageData --------");
        FileInputStream inputStream = null;
        try {
            inputStream = new FileInputStream(path);
            int totalSize = inputStream.available();
            int dataSize = totalSize;
            // int m = 0;
            // if((dataSize % 256) > 0) {
            // m = dataSize / 256;
            // dataSize = (m + 1) * 256;
            // }
            byte[] data = new byte[dataSize];
            inputStream.read(data, 0, dataSize);
            inputStream.close();
            if (isMultipleBin) {
                byte[] binCountByte = new byte[4];
                System.arraycopy(data, 0, binCountByte, 0, binCountByte.length);
                int binCount = ArrayUtil.bytesToIntLittle(binCountByte);
                byte[] mData = new byte[dataSize - (4 + binCount * 8)];
                System.arraycopy(data, (4 + binCount * 8), mData, 0, dataSize - (4 + binCount * 8));
                data = mData;
            }
            mOtaImageData = data;
            int stereo_flg = deviceType == BesOTAConstants.DEVICE_TYPE_STEREO ? 1 : 0;
            if (USER_FLAG == -1 && isSppConnect) {
                stereo_flg = 1;
            }
            packetPayload = ProfileUtils.calculateBLESinglePacketLen(dataSize, mMtu, isBle, stereo_flg) - ll
                    - (isMultipleBin ? 1 : 0);
            if (useTotaV2) {
                packetPayload = (packetPayload - 20) / 16 * 15 + 16;
            }
            totalPacketCount = (dataSize + packetPayload - 1) / packetPayload;
            onePercentBytes = ProfileUtils.calculateBLEOnePercentBytes(dataSize, isBle, stereo_flg);
            curSendPacketLength = packetPayload;
            mDataArr = splitOtaImageData();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public byte[][][] splitOtaImageData() {
        Log.i(TAG, "splitOtaImageData --------");
        int lastArrL = mOtaImageData.length / checkBytesLength + (mOtaImageData.length % checkBytesLength == 0 ? 0 : 1);
        byte[][][] lastArr = new byte[lastArrL][][];
        for (int i = 0; i < lastArrL; i++) {
            int checkPacketDataL =
                    i == (lastArrL - 1) ? (mOtaImageData.length % checkBytesLength == 0 ? checkBytesLength
                            : mOtaImageData.length % checkBytesLength) : checkBytesLength;
            byte[] checkPacketData = new byte[checkPacketDataL];
            System.arraycopy(mOtaImageData, i * checkBytesLength, checkPacketData, 0, checkPacketDataL);
            int packArrL =
                    checkPacketData.length / packetPayload + (checkPacketData.length % packetPayload == 0 ? 0 : 1) + 1;
            byte[][] arr = new byte[packArrL][];
            for (int j = 0; j < packArrL; j++) {
                if (j == (packArrL - 1)) {
                    arr[j] = get82CMD(checkPacketData);
                } else {
                    int packetDataL = j == (packArrL - 2) ? (checkPacketData.length % packetPayload == 0 ? packetPayload
                            : checkPacketData.length % packetPayload) : packetPayload;
                    byte[] packetData = new byte[packetDataL];
                    System.arraycopy(checkPacketData, j * packetPayload, packetData, 0, packetDataL);
                    arr[j] = packetData;
                }
            }
            lastArr[i] = arr;
        }
        return lastArr;
    }

    /**
    public void readlocalImageData(byte[] path, boolean isBle) {
            int totalSize = path.length;
            int dataSize = totalSize;
    
    //            int m = 0;
    //            if((dataSize % 256) > 0) {
    //                m = dataSize / 256;
    //                dataSize = (m + 1) * 256;
    //            }
            byte[] data = path;
            if (isMultipleBin) {
                byte[] binCountByte = new byte[4];
                System.arraycopy(data, 0, binCountByte, 0, binCountByte.length);
                int binCount = ArrayUtil.bytesToIntLittle(binCountByte);
                byte[] mData = new byte[dataSize - (4 + binCount * 8)];
                System.arraycopy(data, (4 + binCount * 8), mData, 0, dataSize - (4 + binCount * 8));
                data = mData;
            }
            mOtaImageData = data;
    
            int stereo_flg = deviceType == BesOTAConstants.DEVICE_TYPE_STEREO ? 1 : 0;
    
            LOG("TAG", "readlocalImageData: -----" + mMtu);
            LOG("TAG", "readlocalImageData: -----" + dataSize);
            LOG("TAG", "readlocalImageData: -----" + isBle);
            if (USER_FLAG == -1 && isSppConnect) {
                stereo_flg = 1;
            }
            packetPayload = ProfileUtils.calculateBLESinglePacketLen(dataSize, mMtu, isBle, stereo_flg) - ll - (isMultipleBin ? 1 : 0);
            if (useTotaV2) {
                packetPayload = (packetPayload - 20) / 16 * 15 + 16;
            }
            Log.i("TAG", "readlocalImageData packetPayload: -----" + packetPayload);
    
            totalPacketCount = (dataSize + packetPayload - 1) / packetPayload;
            onePercentBytes = ProfileUtils.calculateBLEOnePercentBytes(dataSize, isBle, stereo_flg);
            curSendPacketLength = packetPayload;
    }
    **/

    /**
    public byte[] getDataPacket() {
        LOG("TAG", "getDataPacket 1------" + curSendPacketLength);
        LOG("TAG", "getDataPacket 1curSendLength------" + curSendLength);
        LOG("TAG", "getDataPacket 1packetPayload------" + packetPayload);
        LOG("TAG", "getDataPacket 1checkBytesLength------" + checkBytesLength);
    
    //        if (USER_FLAG == 1 && isWithoutResponse) {
            //固定长度校验
    
            int totalBinLength = mOtaImageData.length;
            int curBinSendLength = curSendLength;
            if (isMultipleBin) {
                totalBinLength = curBinLength;
                curBinSendLength = curSendLength - (curBinCheckLength - curBinLength);
            }
            if (beforeSendLength > 0 && crcConfirmTimes == 0) {
                LOG("TAG", "getDataPacket 1checkBytesLength------0");
                crcConfirmTimes = beforeSendLength / checkBytesLength;
                curSendPacketLength = packetPayload;
            }
            else if (curBinSendLength + packetPayload >= totalBinLength) {
                LOG("TAG", "getDataPacket 1checkBytesLength------1");
    
                curSendPacketLength = totalBinLength - curBinSendLength;
                crcConfirm = true;
            }
            else if (curBinSendLength + packetPayload >= checkBytesLength * (crcConfirmTimes + 1)) {
                LOG("TAG", "getDataPacket 1checkBytesLength------2");
    
                curSendPacketLength = checkBytesLength * (crcConfirmTimes + 1) - curBinSendLength;
                crcConfirm = true;
            }
            else {
                LOG("TAG", "getDataPacket 1checkBytesLength------3");
    
                curSendPacketLength = packetPayload;
            }
            if (curSendLength + curSendPacketLength == (crcConfirmTimes + 1) * checkBytesLength) {
                crcConfirm = true;
            }
    //        } else {
    //            //1%校验
    //            if (beforeSendLength > 0 && crcConfirmTimes == 0) {
    //                crcConfirmTimes = beforeSendLength / onePercentBytes;
    //                curSendPacketLength = packetPayload;
    //            }
    //            else if (curSendLength + packetPayload > onePercentBytes * (crcConfirmTimes + 1) || curSendLength + packetPayload == onePercentBytes * (crcConfirmTimes + 1)) {
    //
    //                curSendPacketLength = onePercentBytes * (crcConfirmTimes + 1) - curSendLength;
    //                crcConfirm = true;
    //            }
    //            else if (curSendLength + packetPayload > mOtaImageData.length) {
    //                curSendPacketLength = mOtaImageData.length - curSendLength;
    //                crcConfirm = true;
    //            }
    //            else {
    //                curSendPacketLength = packetPayload;
    //            }
    //        }
        LOG("TAG", "getDataPacket 2------" + curSendPacketLength);
        Log.i("TAG", "getDataPacket: --------" + curSendPacketLength);
        byte[] data = new byte[curSendPacketLength];
    
        LOG("BesOtaCMD", "curSendLength--" + curSendLength);
        LOG("BesOtaCMD", "curSendPacketLength--" + curSendPacketLength);
        LOG("BesOtaCMD", "mOtaImageDataLength--" + mOtaImageData.length);
        System.arraycopy(mOtaImageData, curSendLength, data, 0, curSendPacketLength);
    
        return data;
    }
    **/

    public byte[] getDataPacket() {
        Log.i(TAG, "getDataPacket --------");
        // if (USER_FLAG == 1 && isWithoutResponse) {
        // 固定长度校验

        // int totalBinLength = mOtaImageData.length;
        // int curBinSendLength = curSendLength;
        // if (isMultipleBin) {
        // totalBinLength = curBinLength;
        // curBinSendLength = curSendLength - (curBinCheckLength - curBinLength);
        // }
        if (beforeSendLength > 0 && crcConfirmTimes == 0) {
            crcConfirmTimes = beforeSendLength / checkBytesLength;
        }

        byte[][] packData = mDataArr[crcConfirmTimes];
        byte[] data = packData[checkCount];
        curSendPacketLength = data.length;
        if (checkCount == (packData.length - 1)) {
            openCrcConfirm = true;
        }

        // else if (curBinSendLength + packetPayload >= totalBinLength) {
        // LOG("TAG", "getDataPacket 1checkBytesLength------1");
        //
        // curSendPacketLength = totalBinLength - curBinSendLength;
        //// crcConfirm = true;
        // openCrcConfirm = true;
        // }
        // else if (curBinSendLength + packetPayload >= checkBytesLength * (crcConfirmTimes + 1)) {
        // LOG("TAG", "getDataPacket 1checkBytesLength------2");
        //
        // curSendPacketLength = checkBytesLength * (crcConfirmTimes + 1) - curBinSendLength;
        //// crcConfirm = true;
        // openCrcConfirm = true;
        // }
        // else {
        // LOG("TAG", "getDataPacket 1checkBytesLength------3");
        //
        // curSendPacketLength = packetPayload;
        // }
        // if (curSendLength + curSendPacketLength == (crcConfirmTimes + 1) * checkBytesLength) {
        //// crcConfirm = true;
        // openCrcConfirm = true;
        // }
        // } else {
        // //1%校验
        // if (beforeSendLength > 0 && crcConfirmTimes == 0) {
        // crcConfirmTimes = beforeSendLength / onePercentBytes;
        // curSendPacketLength = packetPayload;
        // }
        // else if (curSendLength + packetPayload > onePercentBytes * (crcConfirmTimes + 1) || curSendLength +
        // packetPayload == onePercentBytes * (crcConfirmTimes + 1)) {
        //
        // curSendPacketLength = onePercentBytes * (crcConfirmTimes + 1) - curSendLength;
        // crcConfirm = true;
        // }
        // else if (curSendLength + packetPayload > mOtaImageData.length) {
        // curSendPacketLength = mOtaImageData.length - curSendLength;
        // crcConfirm = true;
        // }
        // else {
        // curSendPacketLength = packetPayload;
        // }
        // }
        // LOG("TAG", "getDataPacket 2------" + curSendPacketLength);
        // Log.i("TAG", "getDataPacket: --------" + curSendPacketLength);
        // byte[] data = new byte[curSendPacketLength];
        //
        // LOG("BesOtaCMD", "curSendLength--" + curSendLength);
        // LOG("BesOtaCMD", "curSendPacketLength--" + curSendPacketLength);
        // LOG("BesOtaCMD", "mOtaImageDataLength--" + mOtaImageData.length);
        // System.arraycopy(mOtaImageData, curSendLength, data, 0, curSendPacketLength);

        return data;
    }

    private byte[] getCrc32OfSegment(byte[] data) {
        Log.i(TAG, "getCrc32OfSegment --------");
        long crc32 = ArrayUtil.crc32(data, 0, data.length);
        return new byte[] { (byte) crc32, (byte) (crc32 >> 8), (byte) (crc32 >> 16), (byte) (crc32 >> 24) };
    }

    public byte[] getCrc32OfSegment() {
        // if (USER_FLAG == 1 && isWithoutResponse) {
        LOG(TAG, "getCrc32OfSegment: -----" + curSendLength);
        LOG(TAG, "getCrc32OfSegment: -----" + checkBytesLength * crcConfirmTimes);
        Log.i(TAG, "getCrc32OfSegment: -----" + curSendLength);
        Log.i(TAG, "getCrc32OfSegment: -----" + checkBytesLength * crcConfirmTimes);
        int srcPos = checkBytesLength * crcConfirmTimes;
        int curBinSendLength = curSendLength;
        if (isMultipleBin) {
            srcPos = curConfirmLength;
            curBinSendLength = curSendLength - (curBinCheckLength - curBinLength);
        }
        byte[] crcSegmentData = new byte[curBinSendLength - checkBytesLength * crcConfirmTimes];
        System.arraycopy(mOtaImageData, srcPos, crcSegmentData, 0,
                curBinSendLength - checkBytesLength * crcConfirmTimes);

        long crc32 = ArrayUtil.crc32(crcSegmentData, 0, crcSegmentData.length);
        return new byte[] { (byte) crc32, (byte) (crc32 >> 8), (byte) (crc32 >> 16), (byte) (crc32 >> 24) };
        // } else {
        // byte[] crcSegmentData = new byte[curSendLength - onePercentBytes * crcConfirmTimes];
        // System.arraycopy(mOtaImageData, onePercentBytes * crcConfirmTimes, crcSegmentData, 0, curSendLength -
        // onePercentBytes * crcConfirmTimes);
        // long crc32 = ArrayUtil.crc32(crcSegmentData, 0, crcSegmentData.length);
        // return new byte[]{(byte) crc32, (byte) (crc32 >> 8), (byte) (crc32 >> 16), (byte) (crc32 >> 24)};
        // }
    }

    public byte[] getImageOverwritingConfirmationPacketCMD() {
        Log.i(TAG, "getImageOverwritingConfirmationPacketCMD --------");
        byte[] pt = new byte[] { (byte) B_92 };
        byte[] lBytes = emptyByte;
        if (USER_FLAG == 1) {
            lBytes = ArrayUtil.intToBytesLittle(magicCode.length);
        }
        byte[] bytes = ArrayUtil.bytesSplic(pt, lBytes, magicCode, emptyByte);
        if (isTotaConnect) {
            return convertToTotaCMD(bytes);
        }
        return bytes;
    }

    public void notifySuccess() {
        curSendLength += curSendPacketLength;
        LOG(TAG, "notifySuccess: ---------" + curSendLength);
        LOG(TAG, "notifySuccess: ---------" + curConfirmLength);
        Log.i(TAG, "notifySuccess:---------" + curSendLength);
        // Log.i(TAG, "notifySuccess: ---------" + curConfirmLength);
    }

    // onReceive
    public int receiveData(byte[] data, Context context, int curOtaResult, boolean sendPackageWithAck) {
        Log.i(TAG, "receiveData curOtaResult--------" + curOtaResult);
        mContext = context;
        if (data[0] == B_8F) {
            int typeL = pl + ll + magicCode.length;
            deviceTypeBytes = new byte[] { data[typeL] };
            if (data[typeL] == 0x00) {
                Log.i(TAG, "decviceType: ---STEREO");
                deviceType = BesOTAConstants.DEVICE_TYPE_STEREO;
                if (USER_FLAG == 1) {
                    byte[] lb = new byte[4];
                    System.arraycopy(data, pl, lb, 0, ll);
                    int msgL = ArrayUtil.bytesToIntLittle(lb);
                    if (msgL > 15) {
                        byte[] msgBytes = new byte[data.length - (typeL + 8 + 1)];
                        System.arraycopy(data, (typeL + 8 + 1), msgBytes, 0, data.length - (typeL + 8 + 1));
                        versionMsg = ArrayUtil.toASCII(msgBytes).replace("-", " ");
                    }
                }
            } else if (data[typeL] == 0x01) {
                Log.i(TAG, "decviceType: ---TWS_CONNECT_LEFT");
                deviceType = BesOTAConstants.DEVICE_TYPE_TWS_CONNECT_LEFT;
            } else if (data[typeL] == 0x02) {
                Log.i(TAG, "decviceType: ---TWS_CONNECT_RIGHT");
                deviceType = BesOTAConstants.DEVICE_TYPE_TWS_CONNECT_RIGHT;
            }
            int vl = 4;
            byte[] versionL = new byte[vl];
            System.arraycopy(data, typeL + 1, versionL, 0, vl);
            // String versionLStr = ArrayUtil.toHex(versionL);
            String versionLStr = ArrayUtil.toDec(versionL);
            curVersionLeft = versionLStr.replace(",", ".");
            byte[] versionR = new byte[vl];
            System.arraycopy(data, typeL + 1 + vl, versionR, 0, vl);
            String versionRStr = ArrayUtil.toHex(versionR);
            curVersionRight = versionRStr.replace(",", ".");
            return getReturnResult(BesOTAConstants.OTA_CMD_GET_HW_INFO, curOtaResult);
        } else if (data[0] == B_91) {
            destoryVariable();
            int confirmL = pl + ll;
            if (data[confirmL] == CONFIRM_BYTE_PASS) {
                return getReturnResult(BesOTAConstants.OTA_CMD_SELECT_SIDE_OK, curOtaResult);
            }
            return getReturnResult(BesOTAConstants.OTA_CMD_SELECT_SIDE_ERROR, curOtaResult);
        } else if (data[0] == B_8D) {
            int breakpointL = pl + ll;
            byte[] bpLengthBytes = new byte[4];
            System.arraycopy(data, breakpointL, bpLengthBytes, 0, bpLengthBytes.length);
            curSendLength = ArrayUtil.bytesToIntLittle(bpLengthBytes);
            if (curSendLength > 0) {
                beforeSendLength = curSendLength;
                curConfirmLength = curSendLength;
                mMtu = (int) SPHelper.getPreference(mContext, BesOTAConstants.BES_OTA_CURRENT_MTU, mMtu);
                crcConfirmTimes = curSendLength / checkBytesLength;
                return getReturnResult(BesOTAConstants.OTA_CMD_BREAKPOINT_CHECK, curOtaResult);
            } else {
                byte[] bpRandomBytes = new byte[32];
                System.arraycopy(data, breakpointL + bpLengthBytes.length, bpRandomBytes, 0, bpRandomBytes.length);
                SPHelper.putPreference(mContext, BesOTAConstants.BES_OTA_RANDOM_CODE_LEFT + deviceId,
                        ArrayUtil.toHex(bpRandomBytes));
                return getReturnResult(BesOTAConstants.OTA_CMD_BREAKPOINT_CHECK_80, curOtaResult);
            }
        } else if (data[0] == B_81) {
            int vl = pl + ll + magicCode.length;
            byte[] swVersionBytes = new byte[2];
            System.arraycopy(data, vl, swVersionBytes, 0, 2);
            String swVersionBytesStr = ArrayUtil.toHex(swVersionBytes);
            mSwVersion = swVersionBytesStr.replace(",", ".");
            byte[] hwVersionBytes = new byte[2];
            System.arraycopy(data, vl + swVersionBytes.length, hwVersionBytes, 0, 2);
            String hwVersionBytesStr = ArrayUtil.toHex(hwVersionBytes);
            mHwVersion = hwVersionBytesStr.replace(",", ".");
            LOG(TAG, "receiveData: --" + mSwVersion + "--" + mHwVersion);

            byte[] mtuBytes = new byte[4];
            System.arraycopy(data, vl + swVersionBytes.length + hwVersionBytes.length, mtuBytes, 0, 2);
            if (curSendLength > 0 && isMultipleBin) {

            } else {
                mMtu = ArrayUtil.bytesToIntLittle(mtuBytes);
                LOG(TAG, "receiveData mMtu: --" + mMtu);
                SPHelper.putPreference(mContext, BesOTAConstants.BES_OTA_CURRENT_MTU, mMtu);
            }
            return getReturnResult(BesOTAConstants.OTA_CMD_BREAKPOINT_CHECK, curOtaResult);
        } else if (data[0] == B_87) {
            int confirmL = pl + ll;
            if (data[confirmL] == CONFIRM_BYTE_PASS) {
                return BesOTAConstants.OTA_CMD_SEND_CONFIGURE_OK;
            }
            return getReturnResult(BesOTAConstants.OTA_CMD_SEND_CONFIGURE_ERROR, curOtaResult);
        } else if (data[0] == B_83) {
            int confirmL = pl + ll;
            LOG(TAG, "receive 83 curConfirmCrc---" + ArrayUtil.toHex(curConfirmCrc));
            if ((int) data[pl] > 4) {
                byte[] deviceCrc = new byte[4];
                System.arraycopy(data, confirmL + 1, deviceCrc, 0, 4);
                LOG(TAG, "receive 83 deviceCrc---" + ArrayUtil.toHex(deviceCrc));
                if (ArrayUtil.startsWith(curConfirmCrc, deviceCrc)) {
                    curConfirmCrc = new byte[4];
                } else {
                    return 0;
                }
            }
            if (data[confirmL] == CONFIRM_BYTE_PASS) {
                crcConfirmTimes++;
                curConfirmLength = curSendLength;
                crcConfirm = false;
                int totalBinLength = mOtaImageData.length;
                if (isMultipleBin) {
                    totalBinLength = curBinCheckLength;
                }
                if (mOtaImageData != null && curSendLength == totalBinLength) {
                    return BesOTAConstants.OTA_CMD_WHOLE_CRC_CHECK;
                }
                return BesOTAConstants.OTA_CMD_CRC_CHECK_PACKAGE_OK;
            }
            return BesOTAConstants.OTA_CMD_CRC_CHECK_PACKAGE_ERROR;
        } else if (data[0] == B_84) {
            int confirmL = pl + ll;
            if (data[confirmL] == CONFIRM_BYTE_PASS) {
                if (isMultipleBin) {
                    if (curSendLength == mOtaImageData.length) {
                        return BesOTAConstants.OTA_CMD_WHOLE_CRC_CHECK_OK;
                    } else {
                        // 多bin升级是否多次弹框
                        if (curSendLength > 0) {
                            return OTA_CMD_BREAKPOINT_CHECK_80_NO_CHANGE;
                        }
                        return BesOTAConstants.OTA_CMD_BREAKPOINT_CHECK_80;
                    }
                }
                return BesOTAConstants.OTA_CMD_WHOLE_CRC_CHECK_OK;
            }
            return BesOTAConstants.OTA_CMD_WHOLE_CRC_CHECK_ERROR;
        } else if (data[0] == B_93) {
            int confirmL = pl + ll;
            if (data[confirmL] == CONFIRM_BYTE_PASS) {
                return getReturnResult(BesOTAConstants.OTA_CMD_IMAGE_OVER_CONFIRM, curOtaResult);
            }
            return getReturnResult(BesOTAConstants.OTA_CMD_IMAGE_OVER_CONFIRM_ERROR, curOtaResult);
        } else if (data[0] == B_95) {
            return BesOTAConstants.OTA_CMD_DISCONNECT;
        } else if (data[0] == B_96) {
            return BesOTAConstants.OTA_CMD_ROLESWITCH_COMPLETE;
        } else if (data[0] == B_9A) {
            USER_FLAG = 1;
            setOtaUser(USER_FLAG, isSppConnect, isWithoutResponse, isTotaConnect, useTotaV2, deviceId);
            return BesOTAConstants.OTA_CMD_GET_PROTOCOL_VERSION;
        } else if (data[0] == B_98) {
            int confirmL = pl + ll;
            if (data[confirmL] == CONFIRM_BYTE_PASS) {
                return BesOTAConstants.OTA_CMD_SET_OAT_USER_OK;
            } else if (data[confirmL] == CONFIRM_BYTE_LOW_BATTERY) {
                return BesOTAConstants.OTA_START_DEVICE_LOW_BATTERY_ERROR;
            }
            return BesOTAConstants.OTA_CMD_SET_OAT_USER_ERROR;
        } else if (data[0] == B_9E) {
            int confirmL = pl + ll;
            if (data[confirmL] == (byte) 0x01) {
                return BesOTAConstants.OTA_CMD_SET_UPGRADE_TYPE_NORMAL;
            } else if (data[confirmL] == (byte) 0x02) {
                return BesOTAConstants.OTA_CMD_SET_UPGRADE_TYPE_FAST;
            }
        } else if (data[0] == B_9C) {
            String dataStr = ArrayUtil.toHex(data);
            dataStr = dataStr.replace(",", "");
            roleSwitchRandomID = dataStr.substring(dataStr.length() - 4);
            return BesOTAConstants.OTA_CMD_ROLESWITCH_GET_RANDOMID;
        } else if (data[0] == B_8B) {
            if (sendPackageWithAck) {
                return BesOTAConstants.OTA_CMD_SEND_OTA_DATA;
            }
            return BesOTAConstants.OTA_CMD_RETURN;
        } else if (data[0] == B_7F) {
            int confirmL = pl + ll;
            byte[] lb = new byte[4];
            System.arraycopy(data, confirmL, lb, 0, 4);
            curAdjustInterval = ArrayUtil.bytesToIntLittle(lb);
            return BesOTAConstants.OTA_CMD_ADJUST_INTERVAL;
        } else if (data[0] == B_7E) {
            int confirmL = pl + ll;
            byte[] lb = new byte[4];
            System.arraycopy(data, confirmL, lb, 0, 4);
            checkBytesLength = ArrayUtil.bytesToIntLittle(lb);
            return 0;
        } else {
            Log.i(TAG, "receiveData: error");
        }
        return 0;
    }

    public int getCurAdjustInterval() {
        return curAdjustInterval;
    }

    public void crcConfirmError() {
        LOG(TAG, "crcConfirmError---" + curSendLength);
        LOG(TAG, "crcConfirmError---" + curConfirmLength);
        curSendLength = curConfirmLength;
        LOG(TAG, "crcConfirmError---" + curSendLength);
    }

    public int getReturnResult(int state, int curState) {
        if (state <= curState) {
            return BesOTAConstants.OTA_CMD_RETURN;
        }
        return state;
    }

    public String besOtaProgress() {
        if (mOtaImageData == null)
            return "0.00";
        int total = mOtaImageData.length;
        if (total == 0) {
            return "0.00";
        }
        double v1 = curSendLength * 100;
        if (v1 / 100 > total) {
            v1 = total;
        }
        return ArrayUtil.div(v1, total, 2) + "";
    }

    public String besOtaProgress(int length) {
        if (mOtaImageData == null)
            return "";
        int total = mOtaImageData.length;
        long localL = length;
        if (total == 0) {
            return "0.00";
        }
        double v1 = localL * 100;
        if (v1 / 100 > total) {
            v1 = total;
        }
        return ArrayUtil.div(v1, total, 2) + "";
    }

    public void setCrcConfirmState(boolean state) {
        crcConfirm = state;
    }

    public byte[] convertToTotaCMD(byte[] bytes) {
        byte[] lBytes = ArrayUtil.intToBytesLittle(bytes.length);
        byte[] covertBytes = ArrayUtil.bytesSplic(totaOP, new byte[] { lBytes[0] }, new byte[] { lBytes[1] }, bytes);
        Log.i(TAG, "convertToTotaCMD: -------" + ArrayUtil.toHex(covertBytes));
        return covertBytes;
    }

    public void refreshConfirmCrc(byte[] data) {
        curConfirmCrc = data;
    }

    public void LOG(String TAG, String msg) {
        if (mContext == null) {
            return;
        }
        if (OtaLog.isWriteLog) {
            Log.e(TAG, msg);
        }
        if (OtaLog.isWriteFile) {
            LogUtils.writeLog(TAG, msg);
        }
    }

}
